# !/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName  :incremental_and_iteratice_model.py
# @Time      :2025/7/18 10:13
# @Author    :aiyimu

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
from matplotlib.patches import Rectangle, FancyBboxPatch, Circle
import matplotlib.font_manager as fm
from matplotlib import rcParams

# =========================
# 解决中文乱码问题
# =========================
# 方法1：使用支持中文的系统字体（推荐）
try:
    # 设置中文字体 - 尝试多种常见中文字体
    possible_fonts = [
        'SimHei',  # Windows黑体
        'Microsoft YaHei',  # Windows微软雅黑
        'STHeiti',  # MacOS华文黑体
        'Heiti SC',  # MacOS黑体-简
        'WenQuanYi Zen Hei',  # Linux文泉驿正黑
        'WenQuanYi Micro Hei',  # Linux文泉驿微米黑
        'Noto Sans CJK SC'  # Google Noto字体
    ]

    # 检查系统可用的中文字体
    available_fonts = set(f.name for f in fm.fontManager.ttflist)
    for font_name in possible_fonts:
        if font_name in available_fonts:
            plt.rcParams['font.sans-serif'] = [font_name]
            print(f"使用字体: {font_name}")
            break
    else:
        # 方法2：如果找不到系统字体，使用内置字体
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 尝试使用SimHei

    # 解决负号显示问题
    plt.rcParams['axes.unicode_minus'] = False

except:
    # 方法3：终极解决方案 - 指定字体文件路径
    try:
        # 替换为您系统中的中文字体文件路径
        font_path = '/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf'  # Linux示例
        # font_path = 'C:/Windows/Fonts/simhei.ttf'  # Windows示例
        # font_path = '/System/Library/Fonts/PingFang.ttc'  # macOS示例

        font_prop = fm.FontProperties(fname=font_path)
        rcParams['font.family'] = font_prop.get_name()
        print(f"使用字体文件: {font_path}")
    except:
        print("无法加载中文字体，将使用默认字体")

# =========================
# 创建图形和子图
# =========================
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
fig.suptitle('软件工程模型对比：增量模型 vs 迭代模型', fontsize=18, fontweight='bold')

# 设置通用样式
model_title_style = {'fontsize': 14, 'fontweight': 'bold', 'ha': 'center'}
text_style = {'fontsize': 10, 'ha': 'center', 'va': 'center'}

# =========================
# 增量模型示意图
# =========================
ax1.set_title('增量模型 (Incremental Model)', **model_title_style)
ax1.set_xlim(0, 10)
ax1.set_ylim(0, 6)
ax1.axis('off')

# 绘制时间轴
ax1.plot([1, 9], [5.5, 5.5], 'k-', lw=1.5)
for i in range(1, 10):
    ax1.plot([i, i], [5.4, 5.6], 'k-', lw=1.5)
    if i < 9:
        ax1.text(i + 0.5, 5.3, f"增量{i}", ha='center', fontsize=9)

# 绘制增量块
colors = ['#FF9999', '#99FF99', '#9999FF', '#FFCC99']
increments = [
    {"name": "核心功能", "height": 1.5},
    {"name": "用户管理", "height": 2.0},
    {"name": "支付系统", "height": 2.5},
    {"name": "高级功能", "height": 3.0}
]

for i, inc in enumerate(increments):
    # 绘制增量交付物
    y_offset = 0.5
    width = 1.8
    height = inc["height"]
    x = 1 + i * 2 + 0.1

    # 增量块
    ax1.add_patch(Rectangle((x, y_offset), width, height,
                            facecolor=colors[i], alpha=0.8,
                            edgecolor='k', lw=1))

    # 功能分解
    for j in range(3):
        y_pos = y_offset + (j + 0.5) * height / 3
        ax1.text(x + width / 2, y_pos, f"功能{j + 1}", **text_style)

    # 增量标签
    ax1.text(x + width / 2, height + y_offset + 0.2, inc["name"],
             fontsize=11, ha='center', weight='bold')

    # 连接时间轴
    ax1.plot([x + width / 2, x + width / 2], [y_offset + height, 5.4],
             'k--', alpha=0.5, lw=1)

# 添加模型说明
ax1.text(5, 0.2, "▲ 分多个独立增量交付\n"
                 "▲ 每个增量是完整的功能模块\n"
                 "▲ 增量按顺序交付给客户\n"
                 "▲ 早期交付核心功能，逐步添加新功能",
         ha='center', fontsize=11, bbox=dict(facecolor='#FFEECC', alpha=0.7))

# =========================
# 迭代模型示意图
# =========================
ax2.set_title('迭代模型 (Iterative Model)', **model_title_style)
ax2.set_xlim(0, 10)
ax2.set_ylim(0, 6)
ax2.axis('off')

# 绘制时间轴
ax2.plot([1, 9], [5.5, 5.5], 'k-', lw=1.5)
for i in range(1, 10):
    ax2.plot([i, i], [5.4, 5.6], 'k-', lw=1.5)
    if i < 9:
        ax2.text(i + 0.5, 5.3, f"迭代{i}", ha='center', fontsize=9)

# 绘制迭代过程
iterations = [
    {"name": "原型", "size": 0.8, "color": "#FFCCCC"},
    {"name": "基础版本", "size": 1.3, "color": "#FF9999"},
    {"name": "功能增强", "size": 1.8, "color": "#FF6666"},
    {"name": "完整系统", "size": 2.5, "color": "#FF3333"}
]

center_x, center_y = 5, 3

for i, it in enumerate(iterations):
    # 绘制迭代圆
    radius = it["size"]
    circle = Circle((center_x, center_y), radius,
                    color=it["color"], alpha=0.7,
                    edgecolor='k', lw=1)
    ax2.add_patch(circle)

    # 绘制功能点
    angles = np.linspace(0, 2 * np.pi, 8, endpoint=False)
    for j, angle in enumerate(angles):
        func_x = center_x + (radius - 0.2) * np.cos(angle)
        func_y = center_y + (radius - 0.2) * np.sin(angle)
        ax2.text(func_x, func_y, f"{j + 1}", **text_style)

    # 迭代标签
    label_x = center_x + radius + 0.3
    label_y = center_y + radius + 0.2
    ax2.text(label_x, label_y, it["name"],
             fontsize=11, ha='left', weight='bold')

    # 连接时间轴
    if i < len(iterations) - 1:
        next_radius = iterations[i + 1]["size"]
        ax2.plot([center_x + radius, center_x + next_radius],
                 [center_y, center_y], 'k-', lw=1.5)

    # 连接时间轴到迭代
    time_x = 1 + i * 2.5
    ax2.plot([time_x, center_x], [5.4, center_y + radius],
             'k--', alpha=0.5, lw=1)

# 添加核心功能说明
ax2.text(center_x, center_y, "核心功能",
         fontsize=11, ha='center', weight='bold',
         bbox=dict(facecolor='white', alpha=0.8))

# 添加模型说明
ax2.text(5, 0.2, "▲ 重复精化整个系统\n"
                 "▲ 每次迭代都完善所有功能\n"
                 "▲ 早期交付完整但简单的版本\n"
                 "▲ 后续迭代逐步增强功能",
         ha='center', fontsize=11, bbox=dict(facecolor='#CCE8FF', alpha=0.7))

# 添加对比说明
fig.text(0.5, 0.02,
         "关键区别：增量模型每次交付独立功能模块，而迭代模型每次交付完整系统的改进版本",
         ha='center', fontsize=13, fontweight='bold')

plt.tight_layout(rect=[0, 0.05, 1, 0.95])
plt.savefig('incremental_vs_iterative.png', dpi=300, bbox_inches='tight')
plt.show()